"""
控制面板
"""
import tkinter
from tkinter import ttk, filedialog, messagebox
import threading
import time
from typing import Dict, Any, Optional, Callable


class ControlPanel:
    """控制面板 - 纯UI控制层"""

    def __init__(self, parent=None, backend_interface=None):
        self.parent = parent
        self.backend_interface = backend_interface

        # 先初始化所有属性
        self.root = None
        self.ai_control = True
        self.is_training = False
        self.model_frozen = False

        # 统计显示变量 - 必须在setup_ui之前初始化
        self.stats_vars = {}
        self.message_log = []
        self.max_messages = 100

        # UI组件变量初始化
        self.control_mode_var = None
        self.learning_rate_var = None
        self.epsilon_var = None
        self.speed_var = None
        self.frozen_var = None
        self.start_training_btn = None
        self.stop_training_btn = None
        self.message_text = None

        # 更新线程
        self.update_thread = None
        self.running = True

        # 设置UI界面
        self.setup_ui()

        print("控制面板（纯UI）初始化完成")

    def set_backend_interface(self, backend_interface):
        """设置后端接口"""
        self.backend_interface = backend_interface
        self.add_message("后端接口已连接")

    def setup_ui(self):
        """设置UI界面"""
        if self.parent:
            self.root = self.parent
        else:
            self.root = tkinter.Tk()
            self.root.title("RL游戏控制面板")
            self.root.geometry("400x600")

        # 创建主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tkinter.BOTH, expand=True, padx=10, pady=10)

        # 游戏控制区域
        self._create_game_control_section(main_frame)

        # 训练控制区域
        self._create_training_control_section(main_frame)

        # 模型管理区域
        self._create_model_management_section(main_frame)

        # 统计显示区域
        self._create_stats_section(main_frame)

        # 消息日志区域
        self._create_message_log_section(main_frame)

        # 启动更新线程
        self.start_update_thread()

    def _create_game_control_section(self, parent):
        """创建游戏控制区域"""
        game_frame = ttk.LabelFrame(parent, text="游戏控制", padding=10)
        game_frame.pack(fill=tkinter.X, pady=5)

        # 控制模式
        mode_frame = ttk.Frame(game_frame)
        mode_frame.pack(fill=tkinter.X, pady=2)

        ttk.Label(mode_frame, text="控制模式:").pack(side=tkinter.LEFT)

        self.control_mode_var = tkinter.StringVar(value="AI")
        ai_radio = ttk.Radiobutton(mode_frame, text="AI控制", variable=self.control_mode_var,
                                   value="AI", command=self._on_control_mode_change)
        ai_radio.pack(side=tkinter.LEFT, padx=5)

        manual_radio = ttk.Radiobutton(mode_frame, text="手动控制", variable=self.control_mode_var,
                                       value="Manual", command=self._on_control_mode_change)
        manual_radio.pack(side=tkinter.LEFT, padx=5)

        # 游戏操作按钮
        button_frame = ttk.Frame(game_frame)
        button_frame.pack(fill=tkinter.X, pady=5)

        ttk.Button(button_frame, text="重置游戏", command=self._reset_game).pack(side=tkinter.LEFT, padx=2)
        ttk.Button(button_frame, text="暂停/继续", command=self._toggle_pause).pack(side=tkinter.LEFT, padx=2)

        # 手动控制区域
        manual_frame = ttk.LabelFrame(game_frame, text="手动控制", padding=5)
        manual_frame.pack(fill=tkinter.X, pady=5)

        # 方向按钮
        direction_frame = ttk.Frame(manual_frame)
        direction_frame.pack()

        # 上
        ttk.Button(direction_frame, text="↑", width=3,
                   command=lambda: self._manual_action(3)).grid(row=0, column=1, padx=1, pady=1)
        # 左右
        ttk.Button(direction_frame, text="←", width=3,
                   command=lambda: self._manual_action(2)).grid(row=1, column=0, padx=1, pady=1)
        ttk.Button(direction_frame, text="→", width=3,
                   command=lambda: self._manual_action(0)).grid(row=1, column=2, padx=1, pady=1)
        # 下
        ttk.Button(direction_frame, text="↓", width=3,
                   command=lambda: self._manual_action(1)).grid(row=2, column=1, padx=1, pady=1)

    def _create_training_control_section(self, parent):
        """创建训练控制区域"""
        training_frame = ttk.LabelFrame(parent, text="训练控制", padding=10)
        training_frame.pack(fill=tkinter.X, pady=5)

        # 训练按钮
        button_frame = ttk.Frame(training_frame)
        button_frame.pack(fill=tkinter.X, pady=2)

        self.start_training_btn = ttk.Button(button_frame, text="开始训练", command=self._start_training)
        self.start_training_btn.pack(side=tkinter.LEFT, padx=2)

        self.stop_training_btn = ttk.Button(button_frame, text="停止训练", command=self._stop_training,
                                            state=tkinter.DISABLED)
        self.stop_training_btn.pack(side=tkinter.LEFT, padx=2)

        # 训练参数
        params_frame = ttk.Frame(training_frame)
        params_frame.pack(fill=tkinter.X, pady=5)

        # 学习率
        ttk.Label(params_frame, text="学习率:").grid(row=0, column=0, sticky=tkinter.W)
        self.learning_rate_var = tkinter.DoubleVar(value=0.001)
        ttk.Entry(params_frame, textvariable=self.learning_rate_var, width=10).grid(row=0, column=1, padx=5)

        # 探索率
        ttk.Label(params_frame, text="探索率:").grid(row=0, column=2, sticky=tkinter.W, padx=(20, 0))
        self.epsilon_var = tkinter.DoubleVar(value=0.1)
        ttk.Entry(params_frame, textvariable=self.epsilon_var, width=10).grid(row=0, column=3, padx=5)

        # 训练速度
        ttk.Label(params_frame, text="训练速度:").grid(row=1, column=0, sticky=tkinter.W, pady=5)
        self.speed_var = tkinter.DoubleVar(value=1.0)
        speed_scale = ttk.Scale(params_frame, from_=0.1, to=5.0, variable=self.speed_var, orient=tkinter.HORIZONTAL)
        speed_scale.grid(row=1, column=1, columnspan=2, sticky=tkinter.EW, padx=5, pady=5)

        # 配置列权重
        params_frame.columnconfigure(1, weight=1)

    def _create_model_management_section(self, parent):
        """创建模型管理区域"""
        model_frame = ttk.LabelFrame(parent, text="模型管理", padding=10)
        model_frame.pack(fill=tkinter.X, pady=5)

        # 模型操作按钮
        button_frame = ttk.Frame(model_frame)
        button_frame.pack(fill=tkinter.X, pady=2)

        ttk.Button(button_frame, text="保存模型", command=self._save_model).pack(side=tkinter.LEFT, padx=2)
        ttk.Button(button_frame, text="加载模型", command=self._load_model).pack(side=tkinter.LEFT, padx=2)

        # 模型状态
        status_frame = ttk.Frame(model_frame)
        status_frame.pack(fill=tkinter.X, pady=5)

        self.frozen_var = tkinter.BooleanVar(value=False)
        ttk.Checkbutton(status_frame, text="冻结模型", variable=self.frozen_var,
                        command=self._toggle_frozen).pack(side=tkinter.LEFT)

    def _create_stats_section(self, parent):
        """创建统计显示区域"""
        stats_frame = ttk.LabelFrame(parent, text="统计信息", padding=10)
        stats_frame.pack(fill=tkinter.X, pady=5)

        # 创建统计变量
        stats_info = [
            ("轮次", "episode", 0),
            ("回合", "round", 0),
            ("得分", "score", 0),
            ("生命值", "health", 100),
            ("探索率", "epsilon", 0.1),
            ("平均奖励", "avg_reward", 0.0)
        ]

        for i, (label, key, default) in enumerate(stats_info):
            row = i // 2
            col = (i % 2) * 2

            ttk.Label(stats_frame, text=f"{label}:").grid(row=row, column=col, sticky=tkinter.W, padx=5, pady=2)

            var = tkinter.StringVar(value=str(default))
            self.stats_vars[key] = var
            ttk.Label(stats_frame, textvariable=var, foreground="blue").grid(row=row, column=col + 1, sticky=tkinter.W,
                                                                             padx=5, pady=2)

    def _create_message_log_section(self, parent):
        """创建消息日志区域"""
        log_frame = ttk.LabelFrame(parent, text="消息日志", padding=10)
        log_frame.pack(fill=tkinter.BOTH, expand=True, pady=5)

        # 创建文本框和滚动条
        text_frame = ttk.Frame(log_frame)
        text_frame.pack(fill=tkinter.BOTH, expand=True)

        self.message_text = tkinter.Text(text_frame, wrap=tkinter.WORD, height=8)
        scrollbar = ttk.Scrollbar(text_frame, orient=tkinter.VERTICAL, command=self.message_text.yview)
        self.message_text.configure(yscrollcommand=scrollbar.set)

        self.message_text.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=True)
        scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)

        # 清除按钮
        ttk.Button(log_frame, text="清除日志", command=self._clear_messages).pack(pady=5)

    # =========================
    # 事件处理方法（UI逻辑）
    # =========================

    def _on_control_mode_change(self):
        """控制模式改变"""
        mode = self.control_mode_var.get()
        self.ai_control = (mode == "AI")

        if self.backend_interface:
            try:
                self.backend_interface.set_ai_control(self.ai_control)
                self.add_message(f"切换到{'AI控制' if self.ai_control else '手动控制'}模式")
            except Exception as e:
                self.add_message(f"切换控制模式失败: {e}")
        else:
            self.add_message("后端未连接，无法切换控制模式")

    def _reset_game(self):
        """重置游戏"""
        if self.backend_interface:
            try:
                self.backend_interface.reset_game()
                self.add_message("游戏已重置")
            except Exception as e:
                self.add_message(f"重置游戏失败: {e}")
        else:
            self.add_message("后端未连接，无法重置游戏")

    def _toggle_pause(self):
        """暂停/继续"""
        # 这个功能需要后端支持
        self.add_message("暂停/继续功能需要后端实现")

    def _manual_action(self, action: int):
        """执行手动动作"""
        if not self.ai_control and self.backend_interface:
            try:
                result = self.backend_interface.execute_action(action)
                action_names = ["右", "下", "左", "上"]
                action_name = action_names[action] if 0 <= action < len(action_names) else str(action)
                self.add_message(f"执行动作: {action_name}")

                if result and result.get("done"):
                    self.add_message("游戏结束")
            except Exception as e:
                self.add_message(f"执行动作失败: {e}")
        elif self.ai_control:
            self.add_message("请先切换到手动控制模式")
        else:
            self.add_message("后端未连接，无法执行动作")

    def _start_training(self):
        """开始训练"""
        if self.backend_interface:
            try:
                # 获取训练参数
                params = {
                    "learning_rate": self.learning_rate_var.get() if self.learning_rate_var else 0.001,
                    "epsilon": self.epsilon_var.get() if self.epsilon_var else 0.1,
                    "speed": self.speed_var.get() if self.speed_var else 1.0
                }

                self.backend_interface.start_training(params)
                self.is_training = True

                # 更新UI状态
                if self.start_training_btn:
                    self.start_training_btn.config(state=tkinter.DISABLED)
                if self.stop_training_btn:
                    self.stop_training_btn.config(state=tkinter.NORMAL)

                self.add_message("训练已开始")
            except Exception as e:
                self.add_message(f"开始训练失败: {e}")
        else:
            self.add_message("后端未连接，无法开始训练")

    def _stop_training(self):
        """停止训练"""
        if self.backend_interface:
            try:
                self.backend_interface.stop_training()
                self.is_training = False

                # 更新UI状态
                if self.start_training_btn:
                    self.start_training_btn.config(state=tkinter.NORMAL)
                if self.stop_training_btn:
                    self.stop_training_btn.config(state=tkinter.DISABLED)

                self.add_message("训练已停止")
            except Exception as e:
                self.add_message(f"停止训练失败: {e}")
        else:
            self.add_message("后端未连接，无法停止训练")

    def _save_model(self):
        """保存模型"""
        if self.backend_interface:
            try:
                filename = filedialog.asksaveasfilename(
                    title="保存模型",
                    filetypes=[("模型文件", "*.pth"), ("所有文件", "*.*")],
                    defaultextension=".pth"
                )

                if filename:
                    # 提取文件名（不含路径和扩展名）
                    import os
                    model_name = os.path.splitext(os.path.basename(filename))[0]

                    saved_path = self.backend_interface.save_model(model_name)
                    self.add_message(f"模型已保存: {saved_path}")
            except Exception as e:
                self.add_message(f"保存模型失败: {e}")
        else:
            self.add_message("后端未连接，无法保存模型")

    def _load_model(self):
        """加载模型"""
        if self.backend_interface:
            try:
                filename = filedialog.askopenfilename(
                    title="加载模型",
                    filetypes=[("模型文件", "*.pth"), ("所有文件", "*.*")]
                )

                if filename:
                    self.backend_interface.load_model(filename)
                    self.add_message(f"模型已加载: {filename}")
            except Exception as e:
                self.add_message(f"加载模型失败: {e}")
        else:
            self.add_message("后端未连接，无法加载模型")

    def _toggle_frozen(self):
        """切换模型冻结状态"""
        self.model_frozen = self.frozen_var.get() if self.frozen_var else False
        if self.backend_interface:
            try:
                # 假设后端有这个方法
                if hasattr(self.backend_interface, 'freeze_model'):
                    self.backend_interface.freeze_model(self.model_frozen)

                status = "冻结" if self.model_frozen else "解冻"
                self.add_message(f"模型已{status}")
            except Exception as e:
                self.add_message(f"切换模型状态失败: {e}")

    def _clear_messages(self):
        """清除消息日志"""
        if self.message_text:
            self.message_text.delete(1.0, tkinter.END)
        self.message_log.clear()

    # =========================
    # 公共接口方法
    # =========================

    def add_message(self, message: str):
        """添加消息到日志"""
        timestamp = time.strftime("%H:%M:%S")
        formatted_msg = f"[{timestamp}] {message}"

        # 添加到内存日志
        self.message_log.append(formatted_msg)
        if len(self.message_log) > self.max_messages:
            self.message_log.pop(0)

        # 更新UI（线程安全）
        if self.message_text:
            try:
                self.message_text.insert(tkinter.END, formatted_msg + "\n")
                self.message_text.see(tkinter.END)
            except:
                pass  # 忽略UI更新错误

        print(formatted_msg)  # 同时输出到控制台

    def update_stats(self, stats: Dict[str, Any]):
        """更新统计信息显示"""
        for key, value in stats.items():
            if key in self.stats_vars:
                try:
                    # 格式化数值显示
                    if isinstance(value, float):
                        formatted_value = f"{value:.3f}"
                    else:
                        formatted_value = str(value)

                    self.stats_vars[key].set(formatted_value)
                except:
                    pass  # 忽略更新错误

    def start_update_thread(self):
        """启动UI更新线程"""

        def update_loop():
            while self.running:
                try:
                    if self.backend_interface and hasattr(self.backend_interface, 'get_training_stats'):
                        stats = self.backend_interface.get_training_stats()
                        if stats:
                            self.update_stats(stats)
                except:
                    pass  # 忽略更新错误

                time.sleep(1.0)  # 每秒更新一次

        self.update_thread = threading.Thread(target=update_loop, daemon=True)
        self.update_thread.start()

    def destroy(self):
        """销毁控制面板"""
        self.running = False
        if self.update_thread:
            self.update_thread.join(timeout=1)

        if self.root and not self.parent:
            self.root.destroy()

    # =========================
    # 键盘事件处理（可选）
    # =========================

    def bind_keyboard_events(self):
        """绑定键盘事件"""
        if self.root:
            self.root.bind('<Key-Up>', lambda e: self._manual_action(3))
            self.root.bind('<Key-Down>', lambda e: self._manual_action(1))
            self.root.bind('<Key-Left>', lambda e: self._manual_action(2))
            self.root.bind('<Key-Right>', lambda e: self._manual_action(0))
            self.root.bind('<Key-r>', lambda e: self._reset_game())
            self.root.focus_set()  # 确保窗口获得焦点

            self.add_message("键盘控制已启用：方向键控制，R键重置")